<?php
namespace App\Tools;

/**
 *
 *
 * @icon fa fa-circle-o
 */
class Curl
{
    /**
     * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
     * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
     * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
     */

    public function curl_request($action, $params, $contentType = 'urlencoded', $httpMethod = 'POST', $httpHeader = [])
    {
        $ch = curl_init();
        if ($httpMethod == 'POST' && $contentType == 'urlencoded') {
            $httpHeader[] = 'Content-Type:application/x-www-form-urlencoded';
            curl_setopt($ch, CURLOPT_POST, $httpMethod);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $this->build_query($params));

        } elseif ($httpMethod == 'POST' && $contentType == 'json') {
            $httpHeader[] = 'Content-Type:application/json';
            curl_setopt($ch, CURLOPT_POST, $httpMethod);
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params));
        } elseif ($httpMethod == 'GET' && $contentType == 'urlencoded') {
            $action .= strpos($action, '?') === false ? '?' : '&';
            $action .= $this->build_query($params);
        } elseif ($httpMethod == 'PUT' && $contentType == "") {
            $httpHeader[] = 'Content-Type:';
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $httpMethod); //设置请求方式
            curl_setopt($ch, CURLOPT_HTTPHEADER, array("X-HTTP-Method-Override: $httpMethod"));//设置HTTP头信息
            curl_setopt($ch, CURLOPT_POSTFIELDS, $params);//设置提交的字符串
        }

        curl_setopt($ch, CURLOPT_URL, $action);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $httpHeader);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //处理http证书问题
        curl_setopt($ch, CURLOPT_HEADER, false);
        // 在尝试连接时等待的秒数
//        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT , 120);
        // 最大执行时间
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_DNS_USE_GLOBAL_CACHE, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $ret = curl_exec($ch);
        if (false === $ret) {
            $ret = curl_errno($ch);
        }
        curl_close($ch);
        $res = json_decode($ret, true);
        $error = json_last_error();
        if ($error == 0) {
            return $res;
        } else {
            return $ret;
        }
    }

    /**
     * 重写实现 http_build_query 提交实现(同名key)key=val1&key=val2
     * @param array $formData 数据数组
     * @param string $numericPrefix 数字索引时附加的Key前缀
     * @param string $argSeparator 参数分隔符(默认为&)
     * @param string $prefixKey Key 数组参数，实现同名方式调用接口
     * @return string
     */
    public function build_query($formData, $numericPrefix = '', $argSeparator = '&', $prefixKey = '')
    {
        $str = '';
        if (empty($formData)) {
            return $str;
        }
        foreach ($formData as $key => $val) {
            if (!is_array($val)) {
                $str .= $argSeparator;
                if ($prefixKey === '') {
                    if (is_int($key)) {
                        $str .= $numericPrefix;
                    }
                    $str .= urlencode($key) . '=' . urlencode($val);
                } else {
                    $str .= urlencode($prefixKey) . '=' . urlencode($val);
                }
            } else {
                if ($prefixKey == '') {
                    $prefixKey .= $key;
                }
                if (isset($val[0]) && is_array($val[0])) {
                    $arr = array();
                    $arr[$key] = $val[0];
                    $str .= $argSeparator . http_build_query($arr);
                } else {
                    $str .= $argSeparator . $this->build_query($val, $numericPrefix, $argSeparator, $prefixKey);
                }
                $prefixKey = '';
            }
        }
        return substr($str, strlen($argSeparator));
    }
    /***
    * 发送curl请求
    * @param string $url 请求地址
    * @param string $data 携带的post数据
    * @param string $header 请求头
    * @param string $method 请求方式
    * @param string $file 上传文件的路径
    * @return array|bool|string 请求结果
    */
    public function curl_upload($url, $data = '',$header = '' , $method = 'put' , $file = '' )
    {
        $ch = curl_init();
        $params[CURLOPT_URL] = $url;    //请求url地址
        $params[CURLOPT_REFERER] = $url;    //
        if( !empty($header) ) {
            $params[CURLOPT_HTTPHEADER] = $header; //自定义header
        }
        $params[CURLOPT_HEADER] = false; //是否返回响应头信息
        $params[CURLOPT_RETURNTRANSFER] = true; //是否将结果返回
        $params[CURLOPT_FOLLOWLOCATION] = true; //是否重定向
        $params[CURLOPT_TIMEOUT] = 30; //超时时间
        if(!empty($data)){
            $params[CURLOPT_POSTFIELDS] = $data;
        }
        switch ($method){
            case 'get':
                break;
            case 'post':
                $params[CURLOPT_POST] = true;
                break;
            case 'put':
                $params[CURLOPT_PUT] = true;
                $params[CURLOPT_HEADER] = true;
                curl_setopt($ch, CURLOPT_INFILE, fopen($file , 'rb'));
                curl_setopt($ch, CURLOPT_INFILESIZE, filesize($file) );
                curl_setopt($ch, CURLOPT_UPLOAD, true);
                break;
        }
        $params[CURLOPT_SSL_VERIFYPEER] = false;//请求https时设置,还有其他解决方案
        $params[CURLOPT_SSL_VERIFYHOST] = false;//请求https时,其他方案查看其他博文
        //设置桥接(抓包)
//        curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1:8888');
        curl_setopt_array($ch, $params); //传入curl参数
//        curl_setopt($ch, CURLOPT_VERBOSE, true);//curl时debug信息
        // 获得响应结果里的：头大小
//        $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
        //获取请求返回值
        if( $method == 'put' ){
            $content = self::handleHttpResponse( curl_exec($ch) ); //执行
        } else {
            $content = curl_exec($ch); //执行
        }
        // 根据头大小去获取头信息内容
//        $header = substr($content, 0, $headerSize);
        curl_close($ch); //关闭连接
        return $content;
    }

    //处理http响应头字符串数据
    private static function handleHttpResponse( $response = '' ){
        if( empty($response) ){
            return '';
        }
        //转换为数组形式
        $strToArr = array_filter( explode( "\n" , $response ) );

        array_pop( $strToArr );
        //转换为key对value形式
        $data = [];
        foreach ( $strToArr as $k => $v ){
            if( strpos( $v , ':') ){
                $data[substr($v,0 , strpos($v,':'))] = str_replace( '"' , '' , substr($v,strpos($v,' ')) );
            } else {
                $data['code'] = substr($v , strpos( $v , ' ') , 4 );
            }
        }
        return $data;
    }
}
